package org.example.springboot.common.aspect;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.SneakyThrows;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.reflect.MethodSignature;
import org.example.springboot.common.annotation.Loggable;
import org.example.springboot.entity.IrrigationLog;
import org.example.springboot.service.IrrigationLogService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;

import static org.example.springboot.utils.NonNullPropertiesUtil.getNonNullProperties;

@Aspect
@Component
public class LogAspect {
    private static final Logger log = LoggerFactory.getLogger(LogAspect.class);
    @Resource
    private IrrigationLogService irrigationLogService;

    @SneakyThrows
    @Around("@annotation(org.example.springboot.common.annotation.Loggable)")
    public Object log(ProceedingJoinPoint pjp) {
        HttpServletRequest request = getRequest();
        // 记录方法执行前的入参
        Object[] args = pjp.getArgs();

        Object result = null;
        Integer ex = 1;
        try{
            result = pjp.proceed(args);
        }catch (Throwable e){
            log.info("异常信息", e);
            ex = 0;
        }finally {
            IrrigationLog irrigationLog = new IrrigationLog();
            irrigationLog.setUuid(UUID.randomUUID().toString());
            irrigationLog.setUserId(Long.valueOf(request.getHeader("Uid")));
            irrigationLog.setOperationDetail(getAnnotationValue(pjp));
            irrigationLog.setOperationType("01");
            irrigationLogService.save(irrigationLog);
        }
        return result;
    }

    private String getAnnotationValue(ProceedingJoinPoint pjp) {
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method method = signature.getMethod();
        Loggable loggable = method.getAnnotation(Loggable.class);
        return loggable.description();
    }

    private HttpServletRequest getRequest() {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        return (HttpServletRequest) Objects.requireNonNull(requestAttributes).resolveReference(RequestAttributes.REFERENCE_REQUEST);
    }

    //根据HttpServletRequest获取访问者的IP地址
    public static String getIp(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

}